unit palettehelper;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, tilesetgraphicsunit, constants;

type
  TPaletteTile = record
    StartTileId, EndTileId, MainTileId: Integer;
  end;

  TAFirstPaletteDesc = record
    SubBlockId: Byte;
    SelectedAT: Integer;
    OverWater: Boolean;
    IsWaterfall: Boolean;
  end;

const
  SubBlockIds: array [0..15] of TAFirstPaletteDesc = (
    (SubBlockId: 0; SelectedAT: 2048; OverWater: False; IsWaterfall: False), //water
    (SubBlockId: 8; SelectedAT: 2096; OverWater: True; IsWaterfall: False), //deep water
    (SubBlockId: 3; SelectedAT: 2144; OverWater: True; IsWaterfall: False), //reef
    (SubBlockId: 11; SelectedAT: 2192; OverWater: True; IsWaterfall: False), //snowy reef
    (SubBlockId: 4; SelectedAT: 2240; OverWater: False; IsWaterfall: False), //swamp
    (SubBlockId: 7; SelectedAT: 2288; OverWater: False; IsWaterfall: True), //swamp trees
    (SubBlockId: 14; SelectedAT: 2336; OverWater: False; IsWaterfall: False), //lava
    (SubBlockId: 15; SelectedAT: 2384; OverWater: False; IsWaterfall: True), //lava bubbles
    (SubBlockId: 16; SelectedAT: 2432; OverWater: False; IsWaterfall: False), //lake water
    (SubBlockId: 19; SelectedAT: 2480; OverWater: False; IsWaterfall: True), //lake reef
    (SubBlockId: 24; SelectedAT: 2528; OverWater: False; IsWaterfall: False), //frozen lake
    (SubBlockId: 27; SelectedAT: 2576; OverWater: False; IsWaterfall: True), //whirlpool
    (SubBlockId: 20; SelectedAT: 2624; OverWater: False; IsWaterfall: False), //chasm
    (SubBlockId: 23; SelectedAT: 2672; OverWater: False; IsWaterfall: True), //waterfall
    (SubBlockId: 28; SelectedAT: 2720; OverWater: False; IsWaterfall: False), //cloudy surface
    (SubBlockId: 31; SelectedAT: 2768; OverWater: False; IsWaterfall: True) //small clouds
  );

function GetPaletteTile(X, Y: Integer; TileType: Integer; TilesetGraphics: TTilesetGraphics): TPaletteTile;
function IsFullBlock(Flags: Dword): Boolean;

implementation

uses
  autotilehelper;

function GetUpperPaletteTile(X, Y: Integer; TileType: Integer): TPaletteTile;
var
  TileId, LayerOffset: Integer;
begin
  LayerOffset := (TileType - TILE_TYPE_B) * 256;
  TileId := LayerOffset + Y * 8 + X;

  GetUpperPaletteTile.StartTileId := TileId;
  GetUpperPaletteTile.EndTileId := TileId;
  GetUpperPaletteTile.MainTileId := TileId;


end;

function GetAPaletteTile(X, Y: Integer; TilesetGraphics: TTilesetGraphics): TPaletteTile;
var
  RemainingY: Integer;

  function PaletteIndex: Integer; inline;
  begin
    PaletteIndex := RemainingY * 8 + X;
  end;

  function MakeResult(MainId: Integer): TPaletteTile;
  var
    Kind: Integer;
  begin
    Kind := GetAutotileKind(MainId);

    MakeResult.StartTileId := MakeAutotileId(Kind, 0);
    MakeResult.EndTileId := MakeAutotileId(Kind, 47);
    MakeResult.MainTileId := MainId;
  end;

  function GetA1PaletteTile: TPaletteTile;
  begin
    if (PaletteIndex >= Low(SubBlockIds)) and (PaletteIndex <= High(SubBlockIds)) then begin
      GetA1PaletteTile := MakeResult(SubBlockIds[PaletteIndex].SelectedAT);
    end else begin
      GetA1PaletteTile.StartTileId := 0; //TODO: make this actually do something
      GetA1PaletteTile.EndTileId := 0;
      GetA1PaletteTile.MainTileId := 0;
    end;
  end;

  function GetA2PaletteTile: TPaletteTile;
  begin
    GetA2PaletteTile := MakeResult(TILE_ID_A2 + PaletteIndex*48);
  end;

  function GetA3PaletteTile: TPaletteTile;
  begin
    GetA3PaletteTile := MakeResult(TILE_ID_A3 + PaletteIndex*48);
  end;

  function GetA4PaletteTile: TPaletteTile;
  begin
    GetA4PaletteTile := MakeResult(TILE_ID_A4 + PaletteIndex*48);
  end;

  function GetA5PaletteTile: TPaletteTile;
  var
    TileId: Integer;
  begin
    TileId := TILE_ID_A5 + PaletteIndex;
    GetA5PaletteTile.StartTileId := TileId;
    GetA5PaletteTile.EndTileId := TileId;
    GetA5PaletteTile.MainTileId := TileId;
  end;

begin
  RemainingY := Y;

  if TilesetGraphics.HasSet(tgstA1) then begin
    if RemainingY < 2 then begin
      GetAPaletteTile := GetA1PaletteTile;
      Exit;
    end else
      Dec(RemainingY, 2);
  end;

  if TilesetGraphics.HasSet(tgstA2) then begin
    if RemainingY < 4 then begin
      GetAPaletteTile := GetA2PaletteTile;
      Exit;
    end else
      Dec(RemainingY, 4);
  end;

  if TilesetGraphics.HasSet(tgstA3) then begin
    if RemainingY < 4 then begin
      GetAPaletteTile := GetA3PaletteTile;
      Exit;
    end else
      Dec(RemainingY, 4);
  end;

  if TilesetGraphics.HasSet(tgstA4) then begin
    if RemainingY < 6 then begin
      GetAPaletteTile := GetA4PaletteTile;
      Exit;
    end else
      Dec(RemainingY, 6);
  end;

  if TilesetGraphics.HasSet(tgstA5) then begin
    if RemainingY <= 16 then begin
      GetAPaletteTile := GetA5PaletteTile;
      Exit;
    end else begin
        GetAPaletteTile.StartTileId := 0;
        GetAPaletteTile.EndTileId := 0;
        GetAPaletteTile.MainTileId := 0;
    end;
  end;
end;

function GetPaletteTile(X, Y: Integer; TileType: Integer;
  TilesetGraphics: TTilesetGraphics): TPaletteTile;
begin
  if TileType = TILE_TYPE_A then begin
    GetPaletteTile := GetAPaletteTile(X, Y, TilesetGraphics);
  end else begin
    GetPaletteTile := GetUpperPaletteTile(X, Y, TileType);
  end;
end;

function IsFullBlock(Flags: Dword): Boolean;
var
  I: Integer;
begin
  IsFullBlock := True;

  for I := 0 to 3 do begin
    if ((Flags shr I) and 1) = 0 then begin
      IsFullBlock := False;
      Exit;
    end;
  end;

end;



end.

